Skip to content

feat: use system language when no locale has been chosen - #8020

Closed
creeperkatze wants to merge 1 commit into
modrinth:mainfrom
creeperkatze:use-system-language
Closed

creeperkatze wants to merge 1 commit into
modrinth:mainfrom
creeperkatze:use-system-language

Conversation

@creeperkatze

Copy link
Copy Markdown
Contributor

The app always started in English, and the website only used the browser language for logged-out users, since account preferences returned en-US and overrode it. Both now use the system/browser language until one is chosen.

The account localization.locale preference is now nullable and only applied when set. The app detects the language from navigator.languages on startup without saving it, so it follows the OS until one is picked, and a migration resets the stored en-US default. Matching goes through a new shared matchLocale helper in @modrinth/ui, which also prefers a language's home region (e.g. de becomes de-DE instead of de-CH).

Users who chose English on purpose can't be told apart from users who never chose the language, so on a non-English system they'll need to pick English again once. This is unavoidable.

@github-actions

Copy link
Copy Markdown
Contributor

Pull request changelog

App

Added

Changed

Deprecated

Removed

Fixed

Security

Website

Added

Changed

Deprecated

Removed

Fixed

Security

Hosting

Added

Changed

Deprecated

Removed

Fixed

Security

@creeperkatze

Copy link
Copy Markdown
Contributor Author

A minimum translation coverage for detection could be added, so poorly translated languages (e.g. Thai at roughly 11%) fall back to English instead.

Didnt add it since the website already uses the browser language with no threshold, and adding one only to the app would make the two behave differently.

rahul05ranjan

This comment was marked as spam.

@creeperkatze

Copy link
Copy Markdown
Contributor Author

The direction is right — Option<String> with null meaning "follow the system" is the correct model, and folding parseAcceptLanguage's hand-rolled matcher into the shared matchLocale removes a near-duplicate of the same matching logic. The home-region preference in matchLocale (de → de-DE) is a nice touch.

The main thing I'd push back on is the migration asymmetry:

  • packages/app-lib/migrations/20261019120000_detect-system-locale.sql resets every desktop user whose stored locale is en-US to system-detection — including users who deliberately picked English while running a non-English OS. They'll open the app after update and it's suddenly in their system language. If that tradeoff is accepted, it needs a release note, but it's worth checking whether the old app ever wrote en-US on first run without a user choice — if it did, then "explicitly chose English" and "never chose anything" are genuinely indistinguishable and the reset is the only way to give anyone the new behavior. But that should be stated in the migration comment, because as written it looks like a blanket reset.
  • There's no equivalent reset for the server-side web preferences, so web users whose stored localization.locale is en-US stay pinned and never get system detection. Desktop gets flipped even if they chose deliberately; web never gets flipped even if they didn't. One of those two seems wrong.

Two smaller points:

  • language-settings/index.vue: persistedLocale.value = value.localization.locale ?? locale.value means a user in system-detection mode who opens language settings already shows one unsaved "change" (the detected locale), and clicking Save pins it permanently. There's also no way back: once a concrete locale is saved, the selector has no "use system language" option, so the feature is one-way. An explicit auto/system entry in the selector would close both.
  • matchLocale maps bare zh / zh-Hant to whichever zh-* appears first in LOCALES, so a Traditional-Chinese system locale can land on Simplified. The old code had the same flaw, so no regression — just noting it's now the one place this logic lives.

The App.vue guards (locale &&) are consistent with the empty-string sentinel — I checked both watch paths and the settings write is correctly skipped in system mode.

Slop

@mergify

mergify Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

This pull request is closed, so it cannot be queued. Reopen it to get the box back.

@IMB11

IMB11 commented Nov 10, 2026

Copy link
Copy Markdown
Member

Going to close this, I dont think this is smart atm when there are some languages with not great coverage, would make the app pretty weird if they installed for the first time and got greeted with potentially incorrect strings.

@IMB11 IMB11 closed this Nov 10, 2026
@creeperkatze

Copy link
Copy Markdown
Contributor Author

Going to close this, I dont think this is smart atm when there are some languages with not great coverage, would make the app pretty weird if they installed for the first time and got greeted with potentially incorrect strings.

Yea, fair enough. Once localization reaches close to 100% this would be nice to see tho. At least from who I know, most people dont even know the app has a language option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants